#include <stdio.h>
#include <vec3.h>
#include "floatimage.H"

floatimage reduced;
floatimage translucent;
float* reducedData;

void Seperation();
void DataSeperation();
void NormalComputation();
void CalLightDirection();
void DataSampling();
void DataSamplingV2();




void main(int argc, char *argv[])
{

	//reduced.LoadPFM("reducedAlbedoDeep.pfm");
	//translucent.LoadPFM("./input/IMG_0001.pfm");

	//Seperation();	
	//NormalComputation();
	//CalLightDirection();
	//DataSeperation();
	DataSampling();
	//DataSamplingV2();

	//printf("%f",acos(-1.0));

}

void Seperation()
{
	char filename[21] = "./input/IMG_0000.pfm";
	char file[23] = "./output/SPEC_0000.pfm";

	char l, m, n;	

	int index;

	for (int i=1;i<=7;i++)
	{
		floatimage cross;
		floatimage parallel;

		index = i * 2 - 1 + 111;

		l = index / 100;
		m = (index - l * 100) / 10;
		n = index - l * 100 - m * 10;

		l += 48;
		m += 48;
		n += 48;

		filename[13] = l;
		filename[14] = m;
		filename[15] = n;

		//printf(filename);
		//printf("\n");

		parallel.LoadPFM(filename);


		index = i * 2 + 111;

		l = index / 100;
		m = (index - l * 100) / 10;
		n = index - l * 100 - m * 10;

		l += 48;
		m += 48;
		n += 48;

		filename[13] = l;
		filename[14] = m;
		filename[15] = n;

		//printf(filename);
		//printf("\n");

		cross.LoadPFM(filename);


		floatimage output(cross.sizex,cross.sizey);

		for (int i=0;i<output.sizex;i++)
		{
			for (int j=0;j<output.sizey;j++)
			{
				output.point(i,j)=cross.point(i,j) - parallel.point(i,j);

			}

		}

		index = i + 21;

		l = index / 100;
		m = (index - l * 100) / 10;
		n = index - l * 100 - m * 10;

		l += 48;
		m += 48;
		n += 48;

		file[15] = l;
		file[16] = m;
		file[17] = n;

		printf(file);
		printf("\n");

		output.SavePFM(file);


	}
}

void NormalComputation()
{
	char filename[23] = "./output/SPEC_0000.pfm";
	char file[23] = "./output/SPEC_NORM.pfm";

	char l, m, n;	

	int index;

	floatimage gradient[3];
	floatimage invgradient[3];

	for (int i=2;i<=4;i++)
	{
		

		index = i + 21;

		l = index / 100;
		m = (index - l * 100) / 10;
		n = index - l * 100 - m * 10;

		l += 48;
		m += 48;
		n += 48;

		filename[15] = l;
		filename[16] = m;
		filename[17] = n;

		//printf(filename);
		//printf("\n");

		gradient[i-2].LoadPFM(filename);


		index = i + 21 + 3;

		l = index / 100;
		m = (index - l * 100) / 10;
		n = index - l * 100 - m * 10;

		l += 48;
		m += 48;
		n += 48;

		filename[15] = l;
		filename[16] = m;
		filename[17] = n;

		//printf(filename);
		//printf("\n");

		invgradient[i-2].LoadPFM(filename);


	}

	floatimage output(gradient[0].sizex,gradient[0].sizey);

	for (int i=0;i<output.sizex;i++)
	{
		for (int j=0;j<output.sizey;j++)
		{
			output.point(i,j).r=gradient[0].point(i,j).g - invgradient[0].point(i,j).g;
			output.point(i,j).g=gradient[1].point(i,j).g - invgradient[1].point(i,j).g;
			output.point(i,j).b=gradient[2].point(i,j).g - invgradient[2].point(i,j).g;

			output.point(i,j).Normalize();

			output.point(i,j).b += 1;

			output.point(i,j).Normalize();

		}

	}

	/*index = i;

	l = index / 100;
	m = (index - l * 100) / 10;
	n = index - l * 100 - m * 10;

	l += 48;
	m += 48;
	n += 48;

	file[15] = l;
	file[16] = m;
	file[17] = n;

	printf(file);
	printf("\n");*/

	output.SavePFM(file);
}

void CalLightDirection()
{
	FILE *fp;
	FILE *fptr;

	fp = fopen("./input/light.txt","r");
	fptr = fopen("./output/lightdir.txt","w");

	float cx, cy, cr;

	fscanf(fp,"center (%f,%f) r %f\n",&cx,&cy,&cr);

	float incident[11][3];

	fscanf(fp,"\n");

	for (int i=0;i<11;i++)
	{
		float x, y;

		fscanf(fp,"%f %f\n",&x,&y);

		incident[i][0] = x - cx;
		incident[i][1] = y - cy;
		incident[i][2] = sqrt( pow(cr,2) - pow(incident[i][0],2) - pow(incident[i][1],2));

		incident[i][0] /= cr;
		incident[i][1] /= cr;
		incident[i][2] /= cr;

		vec3f normal(incident[i][0],incident[i][1],incident[i][2]);
		vec3f view(0,0,1);

		vec3f reflect = normal * 2 - view;

		reflect = reflect.GetNormalized();

		fprintf(fptr,"%f %f %f\n",reflect[0],reflect[1],reflect[2]);
	}


	fclose(fp);
	fclose(fptr);
}

void DataSeperation()
{
	char filename[21] = "./input/IMG_0000.pfm";
	char file[30] = "./data/degree60/SPEC_0000.pfm";

	char l, m, n;	

	int index;

	for (int i=1;i<=11;i++)
	{
		floatimage cross;
		floatimage parallel;

		index = i * 2 - 1 + 125;

		l = index / 100;
		m = (index - l * 100) / 10;
		n = index - l * 100 - m * 10;

		l += 48;
		m += 48;
		n += 48;

		filename[13] = l;
		filename[14] = m;
		filename[15] = n;

		//printf(filename);
		//printf("\n");

		parallel.LoadPFM(filename);


		index = i * 2 + 125;

		l = index / 100;
		m = (index - l * 100) / 10;
		n = index - l * 100 - m * 10;

		l += 48;
		m += 48;
		n += 48;

		filename[13] = l;
		filename[14] = m;
		filename[15] = n;

		//printf(filename);
		//printf("\n");

		cross.LoadPFM(filename);


		floatimage output(cross.sizex,cross.sizey);

		for (int i=0;i<output.sizex;i++)
		{
			for (int j=0;j<output.sizey;j++)
			{
				output.point(i,j)=cross.point(i,j) - parallel.point(i,j);

			}

		}

		index = i;

		l = index / 100;
		m = (index - l * 100) / 10;
		n = index - l * 100 - m * 10;

		l += 48;
		m += 48;
		n += 48;

		file[22] = l;
		file[23] = m;
		file[24] = n;

		printf(file);
		printf("\n");

		output.SavePFM(file);


	}
}

void DataSampling()
{

	int degree = 60;

	char d_t = degree / 10;
	char d_o = degree % 10;

	d_t += 48;
	d_o += 48;
	

	FILE* fp = fopen("./output/lightdir.txt","r");

	vec3f light[11];

	for (int i=0;i<11;i++)
	{
		fscanf(fp,"%f %f %f\n",&(light[i][0]),&(light[i][1]),&(light[i][2]));
	}

	fclose(fp);

	char file_1[28] = "./data/degree00/regions.txt";
	file_1[13] = d_t;
	file_1[14] = d_o;

	printf(file_1);
	printf("\n");

	FILE* fptr = fopen(file_1,"r");

	int samples;

	fscanf(fptr,"%d\n",&samples);

	int regions[4][4];

	for (int i=0;i<4;i++)
	{
		fscanf(fptr,"h %d %d w %d %d\n",&(regions[i][0]),&(regions[i][1]),&(regions[i][2]),&(regions[i][3]));
	}

	fclose(fptr);

	int issue = 1;
	char d_i = issue + 48;

	char file_11[33] = "./data/degree00/sample0/data00.m";
	file_11[13] = d_t;
	file_11[14] = d_o;
	file_11[22] = d_i;

	char file_com[33] = "./data/degree00/sample0/data01.m";
	file_com[13] = d_t;
	file_com[14] = d_o;
	file_com[22] = d_i;

	issue--;

	printf(file_11);
	printf("\n");

	FILE* data_file = fopen(file_11,"w");
	FILE* data_com = fopen(file_com,"w");

	
	char file[30] = "./data/degree00/SPEC_0000.pfm";
	file[13] = d_t;
	file[14] = d_o;
	char l, m, n;	

	printf(file);
	printf("\n");

	//floatimage SpecAlbedo;
	floatimage NormalMap;

	char file_2[25] = "./output/SPEC_NORM00.pfm";
	file_2[18] = d_t;
	file_2[19] = d_o;

	printf(file_2);
	printf("\n");

	NormalMap.LoadPFM(file_2);

	floatimage AlbedoMap;

	char file_3[25] = "./output/Spec_Albe00.pfm";
	file_3[18] = d_t;
	file_3[19] = d_o;

	printf(file_3);
	printf("\n");

	AlbedoMap.LoadPFM(file_3);

	for (int li=0;li<samples;li++)
	{
		int index = li + 1;

		l = index / 100;
		m = (index - l * 100) / 10;
		n = index - l * 100 - m * 10;

		l += 48;
		m += 48;
		n += 48;

		file[22] = l;
		file[23] = m;
		file[24] = n;

		floatimage SpecAlbedo;

		SpecAlbedo.LoadPFM(file);

		for (int j=regions[issue][0];j<regions[issue][1];j++)
		{
			for (int i=regions[issue][2];i<regions[issue][3];i++)
			{
				//vec3f n(normal.line(j)[i].r,normal.line(j)[i].g,normal.line(j)[i].b);
				//vec3f intensity(diffuse.line(j)[i].r,diffuse.line(j)[i].g,diffuse.line(j)[i].b);

				//float c = n * l;
				//float theta = 180.0*acosf(c)/3.1415926;

				//if (intensity[0]<1e-4||intensity[0]>1e1)
				//{
				//continue;
				//}

				//fprintf(fp,"%f %f\n",theta,intensity[index]);

				float intensity = (SpecAlbedo.line(j)[i].r + SpecAlbedo.line(j)[i].g + SpecAlbedo.line(j)[i].b) / 3.0;
				float albedo = (AlbedoMap.line(j)[i].r + AlbedoMap.line(j)[i].g + AlbedoMap.line(j)[i].b) / 3.0;
				intensity /= albedo;
				vec3f n(NormalMap.line(j)[i].r,NormalMap.line(j)[i].g,NormalMap.line(j)[i].b);
				vec3f ldr(light[li][0],light[li][1],light[li][2]);
				vec3f vdr(0,0,1);
				vec3f hdr = ldr + vdr;
				hdr = hdr.GetNormalized();
				ldr = ldr.GetNormalized();
				n = n.GetNormalized();

				float el, ev;

				el = n * ldr;
				ev = n * vdr;

				intensity = intensity * el * ev * 3.1415926;

				float c = n * hdr;
				float theta = 180.0 * acosf(c) / 3.1415926;

				fprintf(data_file,"%f %f\n",theta,intensity);

				// calculated one

				float intensity_c;
				float n_h_angle = acosf(c);
				float n_l = n * ldr;
				float n_v = n * vdr;
				float n_h = n * hdr;
				float v_h = vdr * hdr;
				float p_m = 0.3788;
				float p_R = 0.4637;

				intensity_c = min(2 * n_h * n_v / v_h, 2 * n_h * n_l / v_h);
				intensity_c = min(intensity_c, 1.0);
				intensity_c *= pow(2.71828, -1.0 * pow(tan(n_h_angle)/p_m,2));
				intensity_c /= (pow(p_m,2)*pow(cos(n_h_angle),4));
				intensity_c *= (p_R + (1 - p_R) * pow(1 - n_l, 5));

				fprintf(data_com,"%f %f\n",theta,intensity_c);


			}
		}
	}	

	fclose(data_file);
	fclose(data_com);

}

void DataSamplingV2()
{
	FILE* fp = fopen("./output/lightdir.txt","r");

	vec3f light[11];

	for (int i=0;i<11;i++)
	{
		fscanf(fp,"%f %f %f\n",&(light[i][0]),&(light[i][1]),&(light[i][2]));
	}

	fclose(fp);

	FILE* fptr = fopen("./data/degree60/regions.txt","r");



	int regions[4][4];

	for (int i=0;i<4;i++)
	{
		fscanf(fptr,"h %d %d w %d %d\n",&(regions[i][0]),&(regions[i][1]),&(regions[i][2]),&(regions[i][3]));
	}

	fclose(fptr);

	FILE* data_file = fopen("./data/degree60/fre_data00.m","w");

	int issue = 3;
	char file[30] = "./data/degree60/SPEC_0000.pfm";
	char l, m, n;	

	//floatimage SpecAlbedo;
	floatimage NormalMap;

	NormalMap.LoadPFM("./output/SPEC_NORM60.pfm");

	for (int li=0;li<11;li++)
	{
		int index = li + 1;

		l = index / 100;
		m = (index - l * 100) / 10;
		n = index - l * 100 - m * 10;

		l += 48;
		m += 48;
		n += 48;

		file[22] = l;
		file[23] = m;
		file[24] = n;

		floatimage SpecAlbedo;

		SpecAlbedo.LoadPFM(file);   


		for (int j=regions[issue][0];j<regions[issue][1];j++)
		{
			for (int i=regions[issue][2];i<regions[issue][3];i++)
			{
				//vec3f n(normal.line(j)[i].r,normal.line(j)[i].g,normal.line(j)[i].b);
				//vec3f intensity(diffuse.line(j)[i].r,diffuse.line(j)[i].g,diffuse.line(j)[i].b);

				//float c = n * l;
				//float theta = 180.0*acosf(c)/3.1415926;

				//if (intensity[0]<1e-4||intensity[0]>1e1)
				//{
				//continue;
				//}

				//fprintf(fp,"%f %f\n",theta,intensity[index]);

				float intensity = (SpecAlbedo.line(j)[i].r + SpecAlbedo.line(j)[i].g + SpecAlbedo.line(j)[i].b) / 3.0;
				vec3f n(NormalMap.line(j)[i].r,NormalMap.line(j)[i].g,NormalMap.line(j)[i].b);
				vec3f ldr(light[li][0],light[li][1],light[li][2]);
				vec3f vdr(0,0,1);
				vec3f hdr = ldr + vdr;
				hdr = hdr.GetNormalized();

				float c = n * ldr;
				float theta = 180.0 * acosf(c) / 3.1415926;

				fprintf(data_file,"%f %f\n",theta,intensity);

			}
		}
	}	

	fclose(data_file);

}